﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Diagnostics;
using haptic.src.engine.sprite;
using haptic.src.engine.design;
using haptic.src.engine.file;
using Microsoft.Xna.Framework.Content;
using haptic.src.engine.core;

namespace haptic.src.engine.resource
{
    public class ResourceManager : Singleton<ResourceManager>
    {
        private class Category
        {
            public Category(Type oType)
            {
                m_oType = oType;
            }
            private Type m_oType;
            public Type oType { get { return m_oType; } }
            public Hashtable m_oResources = new Hashtable();
        }

        #region Constructors
        public ResourceManager()
        {
            m_oCategories.Add(".sprite.xml", new Category(typeof(SpriteData)));
            m_oCategories.Add(".sprite", new Category(typeof(SpriteData)));
        }
        new private static void Create() { Singleton<ResourceManager>.Create(); }
        public static void Create(ContentManager oContent)
        {
            Create();
            ResourceManager.Inst.m_oContent = oContent;
        }
        #endregion

        private Category FindCategory(string sPath)
        {
            string sExt = PathEx.GetFullExtension(sPath);
            if (m_oCategories.ContainsKey(sExt))
                return (Category)m_oCategories[sExt];
            else
                return null;
        }
        private Resource Get(string sVirtualPath, Category oCategory)
        {
            Debug.Assert(oCategory != null);

            Hashtable oResources = oCategory.m_oResources;
            Debug.Assert(oResources != null);

            Resource oRes = null;
            if (oResources.ContainsKey(sVirtualPath))
            {
                oRes = (Resource)oResources[sVirtualPath];
            }
            else
            {
                // Load resource
                Debug.Assert(oCategory.oType != null);
                oRes = Resource.Load(m_oContent, sVirtualPath, oCategory.oType);
                if (oRes != null)
                {
                    oResources.Add(sVirtualPath, oRes);
                }
            }

            return oRes;
        }
        public Resource Get(string sVirtualPath)
        {
            Category oCategory = FindCategory(sVirtualPath);
            if (oCategory == null)
            {
                Log.Error("This file extension is not supported : " + sVirtualPath);
                return null;
            }

            return Get(sVirtualPath, oCategory);
        }
        public T Get<T>(string sVirtualPath) where T : Resource
        {
            Category oCategory = FindCategory(sVirtualPath);
            if (oCategory == null)
            {
                Log.Error("This file extension is not supported : " + sVirtualPath);
                return null;
            }

            if (oCategory.oType != typeof(T))
            {
                Log.Error("Invalid file type : " + sVirtualPath + " (expected : " + typeof(T) + ")");
                return null;
            }

            Resource oRes = Get(sVirtualPath, oCategory);
            Debug.Assert(oRes.GetType() == typeof(T));
            return (T)oRes;
        }

        #region Attributes
        private Hashtable m_oCategories = new Hashtable();
        private ContentManager m_oContent;
        #endregion
    }
}
